package com.dao;

import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.annotation.WebServlet;

public abstract class BaseDao<T> {
	private static final String DRIVERCLASS = "com.mysql.jdbc.Driver";
	private static final String URL = "jdbc:mysql://localhost:3306/easybuy?useUnicode=true&characterEncoding=utf-8";
	private static final String USERNAME = "root";
	private static final String PASSWORD = "root";

	private Class<T> entityClass;
	
	public BaseDao() {
		Type type = this.getClass().getGenericSuperclass();
		ParameterizedType pt = (ParameterizedType) type;
		Type types[] = pt.getActualTypeArguments();
		entityClass = (Class<T>) types[0]; //   ȡ   class    
	}
	
	public Connection getConnection() {
		Connection connection = null;
		try {
			Class.forName(DRIVERCLASS);
			connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return connection;
	}

	
	public void closeAll(Connection conn, Statement st, ResultSet rs) {
		try {
			if (rs != null)
				rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if (st != null)
				st.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if (conn != null)
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	protected int executeUpdate(String sql, Object... params) {
		int result = 0;
		Connection conn = this.getConnection();
		PreparedStatement pstmt = null;
		try {
			pstmt = conn.prepareStatement(sql);
			for (int i = 0; i < params.length; i++) {
				pstmt.setObject(i + 1, params[i]);
			}
			result = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			closeAll(null, pstmt, null);
		}
		return result;
	}

	protected ResultSet executeQuery(String sql, Object... params) {
		Connection conn = this.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			pstmt = conn.prepareStatement(sql);
			for (int i = 0; i < params.length; i++) {
				pstmt.setObject(i + 1, params[i]);
			}
			rs = pstmt.executeQuery();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return rs;
	}
	
	public abstract String getTableName();
	
	public List<T> getAll(String where, Object...pa) {
		
		String sql = "select * from " + getTableName() + " " + where;
		Connection con = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		List<T> list = new ArrayList<T>();
		try {
			//   ȡ    
			con = getConnection();
			//   ȡִ ж   
			st = con.prepareStatement(sql);
			
			for (int i = 0; i < pa.length; i++) {
				st.setObject(i + 1, pa[i]);
			}
			
			System.out.println(sql +","+ pa);
			
			// ִ л ý  
			rs = st.executeQuery();
			//  ȡ          
			ResultSetMetaData rsMd = rs.getMetaData();
			// õ  е     
			int count = rsMd.getColumnCount();
			
			while(rs.next()) {
				//  һ      
				T obj = entityClass.newInstance();
				//        
				for (int i = 0; i < count; i++) {
					String columnName = rsMd.getColumnName(i + 1);
					
					Field field = entityClass.getDeclaredField(columnName);
					
					field.setAccessible(true);
					
					Object value = rs.getObject(columnName);
					
					field.set(obj, value);
					
				}
				
				list.add(obj);
				
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}
		return list;
	}
	
}
